package Thread;

/**
 *创建三个线程,分别打印 A, B, C
 * 通过 wait-notify, 约定线程的打印顺序,先打印 A,然后 B,最后 C
 */

public class Demo27 {
    //创建三个锁对象,用于三个线程,保证打印顺序能够按照要求的顺序打印
    private static Object locker1 = new Object();
    private static Object locker2 = new Object();
    private static Object locker3 = new Object();

    public static void main(String[] args) throws InterruptedException {
        //线程1: 打印 A
        Thread t1 = new Thread(()->{
            for (int i = 0;i < 10;i ++){
                System.out.println("A");
                synchronized (locker1){
                    locker1.notify();//先打印A,然后唤醒locker.wait,在t2线程中执行打印B
                }

                synchronized (locker3){
                    try {
                        locker3.wait();
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        });

        //线程2: 打印 B
        Thread t2 = new Thread(()->{
           for (int i = 0;i < 10;i ++){
               synchronized (locker1){
                   try {
                       locker1.wait();//locker唤醒之后打印 B
                   } catch (InterruptedException e) {
                       throw new RuntimeException(e);
                   }
               }
               System.out.println("B");

               synchronized (locker2){
                   locker2.notify();//打印 B 之后唤醒 locker2
               }
           }
        });

        //线程3: 打印C
        Thread t3 = new Thread(()->{
           for(int i = 0;i < 10;i ++){
               synchronized (locker2){
                   try {
                       locker2.wait();//locker2唤醒之后打印 C
                   } catch (InterruptedException e) {
                       throw new RuntimeException(e);
                   }
               }

               System.out.println("C");

               synchronized (locker3){
                   locker3.notify();//打印 C 之后唤醒locker3,然后再次回到打印 A 的地方

               }
           }
        });

        t1.start();
        t2.start();
        t3.start();

        //主线程先加个sleep,确保所有线程都已经执行到wait了
        Thread.sleep(100);

        synchronized (locker3){
            locker3.notify();
        }
    }
}
/**
 * 如果是不需要循环打印 ABC 只需要两个locker锁对象就可以完成,locker3保证了能循环打印
 *
 */
